package com.calvin.study.config.security;

import javax.annotation.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.calvin.study.service.sys.security.MyUserDetailsService;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

//	@Override
//	protected void configure(HttpSecurity http) throws Exception {
//		http.httpBasic()//开启httpbasic认证
//		.and()
//		.authorizeRequests()
//		.anyRequest()
//		.authenticated();//所有请求都需要登录认证才能访问
//	}
	
	//自定义认证成功处理
	@Resource
	private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
	//自定义认证失败处理
	@Resource
	private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
	@Resource
	private MyUserDetailsService myUserDetailsService;
	
	
	public void configure(HttpSecurity http) throws Exception {
		http
		.csrf()
			.disable()
		.formLogin()
			.loginPage("/login.html")//一旦用户的请求没有权限就跳转到登录页面
			.loginProcessingUrl("/login")//登录表单form中的action地址，处理认证请求的路径
			.usernameParameter("username")//接受登录页面的用户名参数
			.passwordParameter("password")//接受登录页面的密码参数
			//.defaultSuccessUrl("/")//登录认证成功后默认跳转路径
			//.failureUrl("/login.html")
			.successHandler(myAuthenticationSuccessHandler)
			.failureHandler(myAuthenticationFailureHandler)
		.and()
			.authorizeRequests()
			.antMatchers("/login.html","login").permitAll()//放行访问
			//资源鉴权
			.anyRequest().access("@rbacService.hasPermission(request,authentication)")
			//静态分配权限  
			//.antMatchers("/","/biz1","biz2").hasAnyAuthority("ROLE_user","ROLE_admin")
			//.antMatchers("/syslog","sysuser").hasAnyRole("admin")
			//.anyRequest()
			//.authenticated()// 所有请求都需要登录认证才能访问
		.and()
			.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
				.sessionFixation().migrateSession()
				.maximumSessions(1)//同一个用户，最大的客户端登录数量
				.maxSessionsPreventsLogin(false)//同一个账号，只允许一端登录
				//true 已经登录就不允许再次登录
				//false 允许再次登录，但之前登录的账户会被踢下线
				.expiredSessionStrategy(new CustomExpiredSessionStrategy())//自定义处理session超时或踢下线逻辑
		;
	}
	
	//静态配置用户名/密码/角色
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		/*auth.inMemoryAuthentication()
				.withUser("calvin")
				.password(passwordEncoder().encode("123qwe"))
				.roles("user")
			.and()
				.withUser("admin")
				.password(passwordEncoder().encode("123qwe"))
				.roles("admin")*/
			auth.userDetailsService(myUserDetailsService)// 动态从数据中加载用户角色权限信息
				.passwordEncoder(passwordEncoder());// 配置BCrypt加密
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	//资源放行，不经过过滤器链
	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/css/**","/fonts/**","/img/**","/js/**");
	}

}
